#include <OgreRenderWindow.h>

#include <btBulletCollisionCommon.h>
#include <btBulletDynamicsCommon.h>

#include "Core.h"
#include "Ball.h"
#include "BulletTestState.h"


using namespace pong;

static Core* core;

void BulletTestState::load(Core& c) {
	core = &c;
    // Build the broadphase
	broadphase = new btDbvtBroadphase;

    // Set up the collision configuration and dispatcher
	collisionConfig = new btDefaultCollisionConfiguration;
    dispatcher = new btCollisionDispatcher(collisionConfig);

    // The actual physics solver
    solver = new btSequentialImpulseConstraintSolver;

    // The world.
    world = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfig);
    world->setGravity(btVector3(0,-10,0));

    // Do_everything_else_here
	groundShape = new btStaticPlaneShape(btVector3(0,1,0),1);
	groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,-50,0)));

	btRigidBody::btRigidBodyConstructionInfo groundRigidBodyCI(0,groundMotionState,groundShape,btVector3(0,0,0));
	groundRigidBody = new btRigidBody(groundRigidBodyCI);
	world->addRigidBody(groundRigidBody);

    Ogre::Root* const ogreRoot = c.renderer();
	
    //Create a standard SceneManager
	sceneMan = ogreRoot->createSceneManager(Ogre::ST_GENERIC);

	//Make the camera		
    cam = sceneMan->createCamera("camera");
	cam->setNearClipDistance(1);

	//Attach a vieport to the camera from the RenderWindow
	vp = c.renderWindow()->addViewport(cam, 0);
	vp->setBackgroundColour(Ogre::ColourValue::Black);

    cam->setAspectRatio(Ogre::Real(vp->getActualWidth()) / Ogre::Real(vp->getActualHeight()));

    Level box(Ogre::AxisAlignedBox(-50, -50, -70, 50, 50, 70));
    box.render(sceneMan->getRootSceneNode());

    sceneMan->setAmbientLight(Ogre::ColourValue(0.05f, 0.05f, 0.05f));

    Ogre::Light* l = sceneMan->createLight("MainLight");
    l->setDiffuseColour(.5f, 0.2f, 0);
    l->setSpecularColour(Ogre::ColourValue::White);
    //l->setAttenuation(box.boundaries().getSize()., 1, 0, .1f);
    l->setPosition(15,15,15);

    Ogre::SceneNode* camNode = sceneMan->getRootSceneNode()->createChildSceneNode();
    camNode->attachObject(cam);
    camNode->translate(0, 0, 200);
    camNode->lookAt(Ogre::Vector3::ZERO, Ogre::Node::TS_WORLD);
    
	//Controller c(camNode, ogreRoot, keys, mouse);

	ball = new Ball(c, sceneMan->getRootSceneNode(), 0, 1, world);
}

void BulletTestState::unload(Core& c) {
    c.renderWindow()->removeViewport(0);
    sceneMan->destroyCamera(cam);
	c.renderer()->destroySceneManager(sceneMan);
 
    world->removeRigidBody(groundRigidBody);
    delete groundRigidBody->getMotionState();
    delete groundRigidBody;
 
	delete groundShape;

    delete world;
    delete solver;
    delete dispatcher;
    delete collisionConfig;
    delete broadphase;
}

bool BulletTestState::update(Core& c) {
    world->stepSimulation(c.timeSinceLastUpdate(), 10);
	return true;
}

bool BulletTestState::keyPressed(const OIS::KeyEvent& e) {
    if (e.key == OIS::KC_ESCAPE) {
        core->halt();
    }
    return true;
}
